#pragma once
#include "meta.h"
#include <Algorithm/LBVH/object_manager.h>
#include <Geometry/line.h>
#include <Geometry/intersect.h>

namespace shermit {
namespace fitting {
namespace curve {
	template<typename Float_t>
	class BuildManager_Pts : public lbvh::BuildManager<AABB2_SOA<Float_t>> {
	public:
		Float_t half_length;  // half length of the AABB
		nv::vec2<Float_t>* pts;
		int size;

		GENERAL int primSize() const { return size; }

		GENERAL AABB2<Float_t> buildBV(int idx) const {
			return AABB2<Float_t>(pts[idx] - half_length, pts[idx] + half_length);
		}
	};
#if enable_cuda
	template<typename Float_t>
	class QueryManagerDevice_Lines : public lbvh::QueryManager<Line<nv::vec2<Float_t>>, AABB2_SOA<Float_t>> {
	public:
		LineSOA<nv::vec2<Float_t>> lines;
		int size;
		// store
		int bin_size;
		int* isects;
		int* bin_count;

		GENERAL int primSize() const { return size; }

		GENERAL Line<nv::vec2<Float_t>> get(int idx) const {
			return lines.get(idx);
		}

		GENERAL static bool intersect(const Line<nv::vec2<Float_t>>& obj, const AABB2_SOA<Float_t>& _bvs, int idx) {
			return shermit::intersect(obj, _bvs, idx);
		}

		__device__ void storeIntersection(int obj_idx, int lbvh_prim_idx) {
			if (bin_count[lbvh_prim_idx] >= bin_size) return;
			isects[lbvh_prim_idx * bin_size + atomicAdd(bin_count + lbvh_prim_idx, 1)] = obj_idx;
		}
	};
#endif
}
}
}